
import pdb

__all__ = ['dot','mults','addv']

class svm:

    def __init__(self,X=None,D=None,C=0):
        self.X = X
        self.D = D
        self.C = C
        self.N = len(X)
        self.ddXdots = [[] for i in range(self.N)]
        
        self.A = [0 for i in range(self.N)]
        N = self.N
        dot = self.dot
        
        for i in range(N):
            for j in range(N):
                self.ddXdots[i].append(D[i]*D[j]*dot(X[i],X[j]))
        print self.ddXdots

    def objfunc(self):
        
        Asum = sum(self.A)
        total = 0
        for i in range(self.N):
            for j in range(self.N):
                total += self.A[i]*self.A[j]*self.ddXdots[i][j]
        return Asum - 0.5*total

    def objfuncda(self,aindex):

        total = 0
        for i in range(self.N):
            total += self.A[i]*self.ddXdots[aindex][i]

        return 1 - total

    def graddesc(self,rate,limit):

        self.scores = [self.objfunc()]

        print 'score:',self.scores[0]
        for step in range(limit):
            newA = self.A[:]
            for n in range(self.N):
                da = rate*self.objfuncda(n)
                newA[n] = self.A[n]+da
                if newA[n] < 0: newA[n] = 0
            self.A = newA[:]
            self.scores.append(self.objfunc())
            if self.scores[step]==self.scores[step+1] :break

        for i in range(self.N):
            print 'final da (',str(i),'):',rate*self.objfuncda(i)
        self.W = self.mults(self.X[0],self.A[0]*self.D[0])
        for i in range(1,self.N):
            s = self.A[i]*self.D[i]
            self.W = self.addv(self.W,self.mults(self.X[i],s))

        print 'scores:',self.scores[n]
        print 'alpha:',self.A
        print 'step:',step
        print 'weights:',self.W
    
    def dot(self,X1,X2):
        return reduce(lambda x,y : x+y,[X1[i]*X2[i] for i in range(len(X1))])

    def mults(self,X,s):
        return [x*s for x in X]
    
    def addv(self,X,Y):
        return [X[i]+Y[i] for i in range(len(X))]


if __name__=='__main__':

    #from pylab import *
    x = [1,4,3,6,2,1,0,5,7]
    y = [4,1,6,3,1,1,-1,5,4]
    onei = [0,1,4,5,6]
    twoi = [2,3,7,8]
    xone = [x[i] for i in onei]
    yone = [y[i] for i in onei]
    xtwo = [x[i] for i in twoi]
    ytwo = [y[i] for i in twoi]

    #plot(xone,yone,'ro',xtwo,ytwo,'bo')
    #show()
    
    X = [[1,4],[4,1],[3,6],[6,3],[2,1],[1,1],[0,-1],[5,5],[7,4]]
    D = [-1,-1,1,1,-1,-1,-1,1,1]
    #X = [[1,3],[0,4],[3,1],[4,0]]
    #D = [1,1,-1,-1]
    svm = svm(X,D)
    svm.graddesc(0.001,50000)
